Skip to content

JAMES-4210 Generic SASL mechanism extension#3059

Merged
quantranhong1999 merged 8 commits into
apache:masterfrom
quantranhong1999:sasl-modularize
Jul 7, 2026
Merged

JAMES-4210 Generic SASL mechanism extension#3059
quantranhong1999 merged 8 commits into
apache:masterfrom
quantranhong1999:sasl-modularize

Conversation

@quantranhong1999

@quantranhong1999 quantranhong1999 commented Jun 3, 2026

Copy link
Copy Markdown
Member

TODO:

  • SPI
  • IMAP/SMTP encode/decode bridge
  • SaslMechanismRegistry + SaslMechanismLoader
  • Introduce the SaslMechanism(s) implementations
  • Adapt SASL mechanisms for IMAP

Comment thread protocols/api/src/main/java/org/apache/james/protocols/api/sasl/SaslStep.java Outdated
@quantranhong1999 quantranhong1999 marked this pull request as ready for review June 5, 2026 10:19
@quantranhong1999

Copy link
Copy Markdown
Member Author

Hello,

I did try a lot to make the POC ready so far, for IMAP.

I did rebase on the latest master to have the IMAPServerTest split. You can continue reviewing from the JAMES-4210 Introduce SASL mechanism registry commit.

You can just jump to the last commit JAMES-4210 Add custom IMAP SASL extension example to see how we could implement an SASL mechanism extension for IMAP.

Note that I did rush to make this POC alive for IMAP, so of course, review + polish and double-check would be needed later :)

Comment thread examples/custom-imap/src/main/resources/imapserver.xml Outdated
Comment thread protocols/api/src/main/java/org/apache/james/protocols/api/sasl/SaslProtocol.java Outdated

@chibenwa chibenwa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad that we get something more or less working, that's an achievement in itself. Koodo.

Now remain the next step: SIMPLIFY ! ANd rationalize... I'd expect this proposal to be refined so that we drop the extra aaccidental complexity.

Expect the process to take several working day (and to be painful) but we will be happy I believe about the end result!

I'd suggest we rationnalize before extending to other protocols. I'd expect from this protocol an actual code reduction by switching from O(SxP) implementation complexity to O(S+P) complexity where S is the count of SASL mechanism and P the count of protocols - what this implementation do not deliver yet !

@Arsnael Arsnael left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read it, not much to add for now, just minor comments

Comment thread protocols/api/src/main/java/org/apache/james/protocols/api/sasl/SaslStep.java Outdated
Comment thread protocols/api/src/main/java/org/apache/james/protocols/api/sasl/SaslStep.java Outdated
@quantranhong1999 quantranhong1999 changed the title [POC] JAMES-4210 Generic SASL mechanism extension JAMES-4210 Generic SASL mechanism extension Jun 12, 2026

@chibenwa chibenwa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry to be picky, but this work shall be simplified further.

Let's invest more time on it.

@quantranhong1999

Copy link
Copy Markdown
Member Author

Sorry to be picky, but this work shall be simplified further.

Hello, I did attempt to:

  • simplify SASL injection
  • move authentication logic into the SASL layer so we can reuse it for other protocols

*
* @param channelEncrypted whether the underlying transport is encrypted, for example with TLS.
*/
default boolean isAvailableOnTransport(boolean channelEncrypted) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can concider passin a raw ProtocolSession here I think if we want to be more generic

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ImapSession does not extend ProtocolSession, therefore ProtocolSession is not generic enough to be used here...

Unless we refactor ImapSession to extend ProtocolSession, which feels like another core refactoring.

I guess we can live with boolean channelEncrypted for now, and refactor it further later if needed.

private final Authorizator authorizator;

@Inject
public JamesSaslAuthenticator(Authenticator authenticator, Authorizator authorizator) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or can't we rather user SessionProvider ?

How about letting the Sasl mechanism directly play with SessionProvider ? And we just inject SessionProvider within SaslMechanismFacoties ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, we should avoid injecting SessionProvider directly into SASL mechanisms because SessionProvider returns MailboxSession, which is an IMAP/mailbox-specific session object.

For example, if SMTP later reuses OAUTHBEARER, the mechanism should not create a MailboxSession. SMTP only needs the authenticated/authorized identity to update its own SMTP session state and relay/submission policy.

That is why I prefer keeping a small SaslAuthenticator wrapper: mechanisms perform credential validation and authorization, then return a protocol-neutral SaslAuthenticationResult.Success(SaslIdentity). Each protocol remains responsible for initializing its own session model from that identity.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand why we cannot unify this behaviour as well TBH

@Arsnael Arsnael left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read it

quantranhong1999 added a commit to quantranhong1999/james-project that referenced this pull request Jun 17, 2026
@quantranhong1999

Copy link
Copy Markdown
Member Author

I will plan SMTP adoption in another PR.

We can wait to see whether SMTP adoption is well aligned and viable following the SPI introduced, before merging this IMAP work, if needed. But I presume SMTP adoption would be good.

@chibenwa

Copy link
Copy Markdown
Contributor

We can wait to see whether SMTP adoption is well aligned and viable following the SPI introduced, before merging this IMAP work, if needed.

Yes please

Add the shared SASL exchange model: mechanism factories, initial requests, exchange lifecycle, typed steps, identities, authentication results, and failures. Add contract tests documenting one-step, multi-step, delegation, payload copy, and lifecycle behavior.
Add protocols-sasl with James-backed PLAIN, OAUTHBEARER, and XOAUTH2 factories. Move password and token validation into mechanisms through JamesSaslAuthenticator, keep OIDC config per server block, and add unit coverage for PLAIN and OIDC behavior.
Add shared Guice resolution for auth.saslMechanisms, supporting built-in simple names, external FQCNs, server-specific factory creation, duplicate mechanism deduplication, and configured order preservation.
Drive IMAP AUTHENTICATE and LOGIN through the new SASL exchange model. Add IMAP SASL bridge encoding and decoding, final server-data handling, exchange cleanup, typed failure mapping, and preserve mailbox session semantics including delegation.
Resolve SASL mechanisms per IMAP server configuration in Guice, keep default factory override support for custom IMAP packages, and ensure capability and enable processors belong to the same IMAP processor suite.
Remove authentication and OIDC configuration from IMAPServer, ImapSession, and NettyImapSession; SASL configuration now belongs to the mechanism factory layer. Adapt default and Spring IMAP processor creation so JPA/Spring and tests still get proper default mechanisms.
Update the custom IMAP example to provide a configurable SASL mechanism factory through auth.saslMechanisms, covering SASL-IR, continuation, invalid token, and final server-data flows.
Add WebAdmin regression coverage proving IMAP SASL authentication preserves loggedInUser, including delegated authentication where the connected username and logged-in user differ.
@quantranhong1999

Copy link
Copy Markdown
Member Author

Hello,

I just rebased and reworked the commit history. The changes are the same as before.

quantranhong1999 added a commit to quantranhong1999/openpaas-james that referenced this pull request Jul 7, 2026
quantranhong1999 added a commit to quantranhong1999/openpaas-james that referenced this pull request Jul 7, 2026
@quantranhong1999

Copy link
Copy Markdown
Member Author

Green build.

Objections to merging this?

@chibenwa

chibenwa commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

No objection on my side given that we work on a timely manner on Pop3 and manageSieve

@quantranhong1999 quantranhong1999 merged commit 2f7706b into apache:master Jul 7, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants